﻿using Sttplay.Transmission.SerialPortEx;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;

namespace transmission
{
    public enum VerifyType
    {
        CRC_16,
        CRC_16_MSB_LSB
    }

    public class Context
    {
        public const int MAX_SHOW_LINE = 50;
        private long ts;
        protected List<string> recvList = new List<string>();
        protected bool needUpdateUI;
        public string SendText { get; set; }
        public string RecvText { get; set; }
        public string LogText { get; set; }

        public bool HexMode { get; set; }

        public virtual void Send() { }

        public virtual void Tick() { }

        public virtual void Update()
        {
            if (ts == 0)
                ts = GetTimestamp();
            if(GetTimestamp() - ts >= 100)
            {
                Tick();
                ts = GetTimestamp();
            }
        }

        private static long GetTimestamp()
        {
            return (DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1, 0, 0, 0, 0).Ticks) / 10000;
        }
        public string GetRecvBuffer(byte[] buffer)
        {
            if (HexMode)
            {
                string outStr = "";
                if(buffer.Length > 100)
                {
                    for (int i = 0; i < 20; i++)
                    {
                        outStr += Convert.ToString(buffer[i], 16).PadLeft(2, '0');
                        outStr += ' ';
                    }
                    return string.Format("{0} ... \t{1} bytes", outStr, buffer.Length);
                }
                else
                {
                    for (int i = 0; i < buffer.Length; i++)
                    {
                        outStr += Convert.ToString(buffer[i], 16).PadLeft(2, '0');
                        outStr += ' ';
                    }
                    return outStr;
                }
            }
            else
            {
                if (buffer.Length > 100)
                    return string.Format("{0} ... \t{1} bytes", Encoding.UTF8.GetString(buffer, 0, 20), buffer.Length);
                return Encoding.UTF8.GetString(buffer);
            }
                
        }
        public byte[] GetSendBuffer(out string outStr)
        {
            byte[] bs = null;
            outStr = null;
            if (string.IsNullOrEmpty(SendText))
                return bs;
            if (HexMode)
            {
                string[] hexs = null;
                if (!Regex.IsMatch(SendText, @"^[0-9a-fA-F\u0020]+$"))
                {
                    MessageBox.Show(string.Format("16进制数据{0}格式不正确\n参考下面格式\nff f0 00 fe\n不区分大小写，中间用空格分开\n0f可缩写f，00可缩写0\n一个16进制数据长度不得超过2", SendText), "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return null;
                }
                hexs = SendText.Split(" ".ToArray(), StringSplitOptions.RemoveEmptyEntries);
                bs = new byte[hexs.Length];
                outStr = "";
                for (int i = 0; i < hexs.Length; i++)
                {
                    if (hexs[i].Length > 2)
                    {
                        MessageBox.Show(string.Format("16进制数据{0}格式不正确\n参考下面格式\nff f0 00 fe\n不区分大小写，中间用空格分开\n0f可缩写f，00可缩写0\n一个16进制数据长度不得超过2", SendText), "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
                        return null;
                    }
                    bs[i] = Convert.ToByte(hexs[i], 16);
                    outStr += Convert.ToString(bs[i], 16).PadLeft(2, '0');
                    outStr += ' ';
                }
            }
            else
            {
                outStr = SendText;
                bs = Encoding.UTF8.GetBytes(SendText);
            }
            return bs;
        }

        public byte[] Verify(byte[] bs, int offset, int length, VerifyType type)
        {
            if (type == VerifyType.CRC_16)
            {
                return SerialPortEx.CalcCRC16(bs, offset, length);
            }
            else if(type == VerifyType.CRC_16_MSB_LSB)
            {
                byte[] ret = new byte[2];
                byte[] b = SerialPortEx.CalcCRC16(bs, offset, length);
                ret[0] = b[1];
                ret[1] = b[0];
                return ret;
            }
            return null;
        }

        public virtual void Trigger() { }
    }
}
